package org.example.java.util.concurrency.threadlocal;

import java.io.File;
import java.net.MalformedURLException;

/**
 * 这个例子是线程使用的大对象没有释放导致的oom
 * 需要注意的是：class loader 产生的对象 一定要 content = null;
 * -Xmx20M  -XX:+PrintGC
 * @author juntao zhang
 * @date 2015/10/16 13:33
 */
public class ThreadLocalOOM2 {
  CustomClassLoader cl;

  public ThreadLocalOOM2() {
    try {
      cl = new CustomClassLoader(new File("JavaSE/target/classes").toURI().toURL());
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }
  }
  final static ThreadLocal<Object> tl = new ThreadLocal<>();
  public static void main(String[] args) throws Exception {

    final ThreadLocalOOM2 oom = new ThreadLocalOOM2();
    while (true) {

      new Thread() {
        @Override
        public void run() {
          try {
            System.out.println("==begin==");
            //加载器持有加载对象的引用，
            Class<?> clazz = null;

            clazz = oom.cl.loadClass("org.example.java.util.concurrency.threadlocal.ThreadLocalOOM2$Content");
            Object content = clazz.newInstance();
            System.out.println("main:" + content.toString());
            tl.set(content);

//            tl.set(null);//@1
            tl.remove();//@2
//            content = null;//@4

            /////////////////////////////////////////
            //@1 @4 not oom
            //@2 @4 not oom
            /////////////////////////////////////////
            System.out.println("request gc");
            System.gc();
            Thread.sleep(5000);
            System.out.println("==end==");
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }.start();
      Thread.sleep(50);
    }
  }

  public static class Content {
    byte data[] = new byte[1024 * 1024 * 5];

    protected void finalize() {
      System.out.println(this.toString());
      System.out.println("I am released");
    }
  }
}


